#pragma once
#pragma once
#include "../src_basics/utils.h"
#include "../src_basics/dataStructAlg.h"
#include "../src_post/PostProcessing.h"

class SlideLine {
public:
	SlideLine() :m_mode(0) {}
	SlideLine(int mode) :m_mode(mode) {}
	~SlideLine() {}

	//1.推线
	int pushSingleLine(std::vector<Line>& polyLines, Line& slideLine, const Point offset, const bool postOn);
	//2.推Pin
	int pushOnePt(std::vector<Line>& polyLines, Point& pt, const Point offset);


	//参数接口
	void setMode(int mode) { m_mode = mode; }
	void setInGreed(bool inGreed) { m_inGreed = inGreed; }

//private:
	//算法参数
	int m_mode = 0;		//0推wire点，1推Pin
	bool m_inGreed = false;
	PostProcessingV2 post2;


private:
	//算法运行参数
	double MIN_NUM = 1;				// 推挤线的最短长度
	bool critical_value = false;	// 判断当前推挤线段是否到达临界情况

	//辅助函数
	//1. 推线
	void determineConnection(std::vector<Line>& lineVec, int index, Line& slideline);
	void inspectSingleLines(Line& slideLine, std::vector<Line>& lineVec);
	void pushSingleSeg(Line& line, const Point& offset);
	Point getSlideProjection(const Point& offsetVec, const Point& baseVec);
	Point getPINCrossingPoint(Point referencePoint, Line slideline, bool front);
	bool judgement(Line preLine, const Line& line) const;
	void slidePostProcessing(std::vector<Line>& polyLines);

	//2.推Pin
	int getPtLines(const std::vector<Line>& lines, const Point& pt, bool& isPt1);  //获取点在折线中的线段索引,pt在lines[res].Pt2,起点返回-1


	// Hug============================================================================================================================================================
public:
	double WireWidth = 0;									// 线宽
	int slideMode = 0;										// 推挤模式  [1] slideMode = 0: "off" ;[2] slideMode = 1: "hug" ;[2] slideMode = 2: "shove"
	double LinesSpacing = 191000;							// 最小线间距
	double DPairsSpacing = 10;								// 差分线间距
	double fingerSpacing = 20;								// 默认金手指间的间距

	struct LinesHash {
		size_t operator()(const Line& data) const {
			return std::hash<double>()(data.Pt1.x) ^ std::hash<double>()(data.Pt2.y); //^ std::hash<double>()(data.Pt2.x);
		}
	};
	struct PointsHash {
		size_t operator()(const Point& data) const {
			return std::hash<double>()(data.x) ^ std::hash<double>()(data.y); //^ std::hash<double>()(data.Pt2.x);
		}
	};
	std::unordered_set<Line, LinesHash> tmpHugSegs;  // HugSegments

	

	void setFingerSpacing(double gap) { fingerSpacing = gap; }
	void setMIN_NUM(double value) { MIN_NUM = value; }				//设置推挤线Miter
	void setSlideMode(int value) { slideMode = value; }				//设置推挤模式
	void setLinesSpacing(double value) { LinesSpacing = value; }	//设置最小线间距
	void setWireWidth(const double value) { WireWidth = value; }	//设置最小线宽
	void setDPairsSpacing(double value) { DPairsSpacing = value; }	//设置差分线间距

	void HugPreferred(std::vector<Line>& lineVec, Line hugLine, Line preHugline, std::vector< std::vector<Line>>& obstaclesVec);  //新的单根线的hug
	void HugPreferred(Wire& singleWire, const Line& HugSegment, const Line& preHugSegment, const std::vector<Polygon>& polyObstacles); // 11-21 Update



	//SlideLine
	bool hugOtherSide = false;                                // 换边hug绕走的标志位
	bool hugChange = false;                                   // hug 状态交替的标志 一般为假 ，触发时各线的状态依次重现
	Point NormalHugDir;                                       // 各分组的标准Hug方向  --- 2024/3/27 GeUpdate
	Line tempSlideHugSeg_;                                    // 刚处理后的SlideSeg  --- 2024/3/27 GeUpdate
	std::vector<Line> recordShoveVecLine;                     // 记录成功推挤的线组（在shove中去推挤的时候）
	std::vector<Line> tempHugOnlyLines;                       // 记录此时hugOnly完的线组
	std::vector<Line> recordProHugLines;					  // 记录刚处理完的SlideLinevec  --- 2024/3/27 GeUpdate
	std::vector<std::vector<Line> > lastState_PolyLines;      // 存储上一个触发DRC间距时的调整后的所有hug线的数据
	std::vector<std::vector<Line> > shovedPolyLinesRecord;    // 记录shove模式成功被shove的多根线组
	std::vector<std::vector<Line> > shovingPolyLinesRecord;   // 记录shove模式成功去shove别的线的多根线组
	std::vector<std::vector<Line> > BusHugPolyLinesRecord;    // 记录BusHug模式成功Hug的多根线组

	void BusHugPreferred(std::vector<Wire>& BusHugWires, const std::vector<Line>& PreSlideSegments, const std::vector<Line>& SlideSegments, const std::vector<Polygon>& obstaclesP, const bool& isHaveWireObs);  // Bus 的 Hug
	void polyLinesHug(std::vector<std::vector<Line> >& vec_polyLines, std::vector<Line> prePushLines, std::vector<Line> hugLines, std::vector<std::vector<Line> > obstacle, const bool& haveWireObs); // 多根线的hug
	std::vector<Line> generateOctagon(const Line& BaseCircle, const Line& hugLine);   // 求一个圆的外接正八边形
	std::vector<Line> polygonExpand(std::vector<Line> obstacle, double dist, bool close);  //线和多边形的外扩
	std::vector<std::vector<Line> > polygonUnion(std::vector<std::vector<Line> >obstacles);   //合并重叠的多边形为一个
	Point getCircleVertix(Point vec, double rotateAngle, Point circleP, double radius); // 得到圆的外切正八边形的两个顶点CD
	void CountProcessHugPoints(const std::vector<Line>& singleWires, const std::vector<Line>& ExpandedWires, std::vector<Point>& HugPoints);   // 新的计算可能的Hug点—— 11.14
	std::vector<Line>polyHugPointsHugLink(std::vector<Point>& hugPoints, const std::vector<Line>& singleObstacle, const std::vector<Line>& singleWireVec, const bool& processMode);  //单障碍物多Hug点求解最佳HugSegments
	void HugPostProcessing(std::vector<Line>& hugSegments, const std::vector<std::vector<Line>>& existedObstacles);             // 线形后处理
	std::vector<Line> getMaySlideLines(const std::vector<Line>& InputLines, const Line& BaseSegment, const std::vector<Line>& BaseWireSegs, const double& SlideSegsGap);   // 从一根线中返回多根可能的SlideSegments
	void CleanPointsNotOnObstacle(std::vector<Point>& HugPoints, const std::vector<Line>& singleObstacle);  // 清除不在障碍物边上的点
	void DetermineConnection(std::vector<Line>& lineVec, int index, Line& slideline); // 确定推挤线和其他线的连接关系
	bool BusCheckAfterHug(std::vector<std::vector<Line> >& InputBusWires, const std::vector<std::vector<Line> >& Onstacles);     // Hug 后的 Bus 线检查
	bool CheckSingleWireObs(const std::vector<Line>& inputLines, const std::vector<Line>& SingleObs);  // 检查单根线和障碍物的位置关系
	std::vector<Line> GroupLinesExpand(const std::vector<Line>& inputGroupSegs, const double& StandardSpacing);  // 单根线的外扩（不同部分外扩不同的值）
	void CheckHugSegmentsRight(std::vector<Line>& HugSegments);   // 检查Hug的结果线组有没有问题
	bool CheckTwoWiresCross(const std::vector<Line>& WireOne, const std::vector<Line>& WireTwo, const bool& CheckEnding);  // 判断两个线组是否含有交点
	void exchangeTwoDPairsVec(PairWires& PairsLeft, PairWires& PairsRight);   // 交换两个差分对
	void CheckHugPointsUniqueness(std::vector<Point>& HugPoints);     // HugPoints唯一性检查
	bool TwoHugPointsOnSameSeg(const Point& FirstPoint, const Point& SecondPoint, const std::vector<Line>& singleWire);   // 判断一根线的两点是否在同一根线上 
	std::vector<Line> TwoPointsGetHugSegments(const Point& StartPoint, const Point& EndingPoint, const std::vector<Line>& avoidObstacle, const std::vector<Line>& ExistedSegments);  //新的两点之间直接取Hug线段的方案

	bool IntersectionPointsVec(const std::vector<Point>& pointsVec1, const std::vector<Point>& pointsVec2); //判断点集pointsVec2中含有pointsVec1中的点否





};